package com.mxchip.livestarmobile.mobile.repository

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.mxchip.livestarmobile.mobile.constant.RxConstant
import com.mxchip.livestarmobile.mobile.util.Log.FileLog
import com.mxchip.livestarmobile.mobile.util.RxBus.RxBus
import com.videohigh.hxb.roomclient.*
import com.videohigh.hxb.roomclient.action.*
import com.videohigh.hxb.roomclient.event.*
import io.socket.client.Ack
import java.text.SimpleDateFormat
import java.util.*

object RoomClientRepository {

    private const val TAG = "RoomClientRepository"

    private val stateLiveData = MutableLiveData<Boolean>(true)

    private val socketClient = MeetingSocketClient()

    private val logger = FileLog.getLogger(RoomClientRepository::class.java)

    val isConnect: LiveData<Boolean>
        get() = stateLiveData

    private val callback: MeetingSocketCallback = object : AbsMeetingSocketCallback() {

        override fun onConnect() {
            stateLiveData.postValue(true)
            RxBus.get().post(RxConstant.REGISTER_SUCCESS_NOTIFY_MAIN_ACTIVITY, true)
        }

        override fun onLoginSuccess() {

        }

        override fun onDisconnect() {
            Log.e(TAG, "onDisconnect")
            stateLiveData.postValue(false)
            RxBus.get().post(RxConstant.DISCONNECT, true)
        }

        override fun onReConnectError() {
            Log.e(TAG, "onReConnectError")
            stateLiveData.postValue(false)
        }

        override fun onReConnect() {
            RxBus.get().post(RxConstant.RECONNECT, true)
        }

        override fun onShareContentAdd(event: ShareContentAddEvent) {

            RxBus.get().post(RxConstant.SHARE_CONTENT_ADD_EVENT, event)
        }

        override fun onShareContentRemove(event: ShareContentRemoveEvent) {

            RxBus.get().post(RxConstant.SHARE_CONTENT_REMOVE_EVENT, event)
        }


        override fun onHangup(event: HangupEvent) {
            Log.e(TAG, SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " HangupEvent result:" + event)
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " HangupEvent result:" + event)
            RxBus.get().post(RxConstant.HANGUP_EVENT, event)
        }

        override fun onEnter(event: EnterEvent) {
            Log.e(TAG, SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " EnterEvent result:" + event)
            RxBus.get().post(RxConstant.ENTER_EVENT, event)
        }

        override fun onInvitation(event: InvitationEvent) {
            Log.e(TAG, SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " InvitationEvent result:" + event)
            RxBus.get().post(RxConstant.INVITATION_EVENT, event)
        }

        override fun onVideoDeviceAdd(event: VideoDeviceAddEvent) {
            Log.e(TAG, SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " VideoDeviceAddEvent result:" + event)
        }

        override fun onVideoDeviceRemove(event: VideoDeviceRemoveEvent) {
            Log.e(TAG, SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " VideoDeviceRemoveEvent result:" + event)
        }
    }

    fun init(userId: String, deviceToken: String, roomId: String, clientType: String) {
        socketClient.addCallbackHandler(callback)
        socketClient.init(userId, deviceToken, roomId, clientType)
    }

    fun connect() {
        socketClient.connect()
    }

    fun disconnect() {
        socketClient.disconnect()
    }

    fun connected(): Boolean {
        return socketClient.connected()
    }

    fun hangup(roomId: String, channelId: String, callIndex: String) {
        if (connected()) {
            socketClient.hangup(roomId, channelId, callIndex, {
                logger.info(SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.CHINA).format(Date()) + " hangup $it")
            }, { errorCode, message ->

            })
        } else {
            stateLiveData.postValue(false)
        }
    }

    fun makeCall(number: String?, termIds: Array<String> = emptyArray()) {

        socketClient.makeCall(number, termIds, { resp ->
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " makeCall ack:" + resp)
            RxBus.get().post(RxConstant.MAKE_CALL_RESP, resp)
        }, { errorCode, message ->

        })

        /*socketClient.inviteRequest(groupId, termIds) { resp ->
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " makeCall ack:" + resp)
            stateLiveData.postValue(State.CALLING)
            RxBus.get().post(resp)
        }*/
    }

    fun invite(roomId: String, channelId: String, callIndex: String, numbers: Array<String> = emptyArray()) {

        socketClient.invite(roomId, channelId, callIndex, numbers, { resp ->
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " invite ack:" + resp)
        }, { errorCode, message ->

        })
    }


    fun addShareContent(roomId: String, channelId: String, callIndex: String, deviceName: String, action: ((ShareContentResp) -> Unit)? = null) {


        socketClient.addShareContent(roomId, channelId, callIndex, deviceName, { resp ->
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " addShareContent ack:" + resp)
            action?.invoke(resp)
        }, { errorCode, message ->

        })
    }

    fun removeShareContent(roomId: String, channelId: String, callIndex: String, deviceName: String, action: ((ShareContentResp) -> Unit)? = null) {
        Log.d(TAG, "RoomClientRepository::removeShareContent: ")

        socketClient.removeShareContent(roomId, channelId, callIndex, deviceName, { resp ->
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " removeShareContent ack:" + resp)
            action?.invoke(resp)
        }, { errorCode, message ->

        })
    }


    fun addVideoDevice(roomId: String, channelId: String, callIndex: String, deviceNames: Array<String> = emptyArray()) {
        socketClient.addVideoDevice(roomId, channelId, callIndex, deviceNames, null, null)
    }

    fun removeVideoDevice(roomId: String, channelId: String, callIndex: String, deviceNames: Array<String> = emptyArray()) {
        socketClient.removeVideoDevice(roomId, channelId, callIndex, deviceNames, null, null)
    }

    fun enterChannel(role: Int, roomId: String, channelId: String, callIndex: String, action: ((EnterChannelResp) -> Unit)?) {
        if (connected()) {
            Log.e(TAG, "enterChannel socketClient.enterChannel")
            socketClient.enterChannel(role, roomId, channelId, callIndex, {
                action?.invoke(it)
            }, { errorCode, message ->

            })
        }
    }

    fun keepAliveChannel(roomId: String, channelId: String, callIndex: String, action: ((KeepAliveChannelResp) -> Unit)?) {
        if (connected()) {
            socketClient.keepAliveChannel(roomId, channelId, callIndex, action, { errorCode, message ->

            })
        }
    }


    fun getStates(termNumbers: Array<String>, action: ((GetStatesResp) -> Unit)?) {
        if (connected()) {
            socketClient.getStates(termNumbers, action, { errorCode, message ->

            })
        }
    }

    fun syncChannel(roomId: String, channelId: String, callIndex: String, action: ((SyncChannelResp) -> Unit)?) {
        Log.e(TAG, "syncChannel: $roomId $channelId $callIndex ${connected()}")
        if (connected()) {
            socketClient.syncChannel(roomId, channelId, callIndex, action, { errorCode, message ->

            })
        }
    }


    fun syncAndKeepAliveChannel(roomId: String, channelId: String, callIndex: String, action: ((SyncAndKeepAliveChannelResp) -> Unit)?) {
        Log.e(TAG, "syncChannel: $roomId $channelId $callIndex ${connected()}")
        if (connected()) {
            socketClient.syncAndKeepAliveChannel(roomId, channelId, callIndex, action, { errorCode, message ->

            })
        }
    }


    fun test(o: Any) {
        socketClient.newTest(o) {

        }
    }

    fun addCallbackHandler(callback: MeetingSocketCallback) {
        socketClient.addCallbackHandler(callback)
    }

    fun removeCallbackHandler(callback: MeetingSocketCallback) {
        socketClient.removeCallbackHandler(callback)
    }


    init {
        // socketClient.addCallbackHandler(callback)
    }

    fun destroy() {
        socketClient.destroy()
    }
}